package org.light.oracle.core;

import java.util.Set;
import java.util.TreeSet;

import org.light.core.SpringMVCController;
import org.light.core.Verb;
import org.light.domain.Dao;
import org.light.domain.DaoImpl;
import org.light.domain.Domain;
import org.light.domain.ManyToMany;
import org.light.domain.Method;
import org.light.domain.Prism;
import org.light.domain.Service;
import org.light.domain.ServiceImpl;
import org.light.domain.Type;
import org.light.domain.ValidateInfo;
import org.light.easyui.EasyUIManyToManyTemplate;
import org.light.exception.ValidateException;
import org.light.generator.JsonPagingGridJspTemplate;
import org.light.generator.NamedUtilMethodGenerator;
import org.light.limitedverb.CountAllPage;
import org.light.limitedverb.CountSearchByFieldsRecords;
import org.light.limitedverb.DaoOnlyVerb;
import org.light.limitedverb.NoControllerVerb;
import org.light.oracle.easyui.OracleEasyUIPageTemplate;
import org.light.oracle.generator.MybatisOracleDaoXmlDecorator;
import org.light.oracle.limitedverb.CountActiveRecords;
import org.light.oracle.oracleverb.Activate;
import org.light.oracle.oracleverb.ActivateAll;
import org.light.oracle.oracleverb.Add;
import org.light.oracle.oracleverb.Clone;
import org.light.oracle.oracleverb.CloneAll;
import org.light.oracle.oracleverb.Delete;
import org.light.oracle.oracleverb.DeleteAll;
import org.light.oracle.oracleverb.Export;
import org.light.oracle.oracleverb.ExportPDF;
import org.light.oracle.oracleverb.FilterExcel;
import org.light.oracle.oracleverb.FilterPDF;
import org.light.oracle.oracleverb.FindById;
import org.light.oracle.oracleverb.FindByName;
import org.light.oracle.oracleverb.ListActive;
import org.light.oracle.oracleverb.ListAll;
import org.light.oracle.oracleverb.ListAllByPage;
import org.light.oracle.oracleverb.SearchByFields;
import org.light.oracle.oracleverb.SearchByFieldsByPage;
import org.light.oracle.oracleverb.SearchByName;
import org.light.oracle.oracleverb.SoftDelete;
import org.light.oracle.oracleverb.SoftDeleteAll;
import org.light.oracle.oracleverb.Toggle;
import org.light.oracle.oracleverb.ToggleOne;
import org.light.oracle.oracleverb.Update;
import org.light.utils.StringUtil;

public class OraclePrism extends Prism{
	
	protected MybatisOracleDaoXmlDecorator mybatisOracleDaoXmlDecorator = new MybatisOracleDaoXmlDecorator();

	public OraclePrism() {
		super();
	}

	@Override
	public void generatePrismFiles() throws ValidateException {
		ValidateInfo info = this.validate();
		if (info.success() == false) {
			ValidateException e = new ValidateException(info);
			throw e;
		}
		try {
			String projectFolderPath = folderPath.replace('\\', '/');
			String srcfolderPath = projectFolderPath;
			if (this.packageToken != null && !"".equals(this.packageToken)){
				srcfolderPath = folderPath + "src/main/java/" + packagetokenToFolder(this.packageToken);

				writeToFile(srcfolderPath + "domain/"+StringUtil.capFirst(this.getDomain().getStandardName()) + ".java",
					this.getDomain().decorateCompareTo().generateClassString());
			
				if (this.getDao() != null) {
					writeToFile(
							srcfolderPath + "dao/" +StringUtil.capFirst(this.getDomain().getStandardName()) + "Dao.java",
							this.getDao().generateDaoString());
				}
	
				if (this.getDaoImpl() != null) {
					writeToFile(
							folderPath + "src/main/resources/mapper/" +StringUtil.capFirst(this.getDomain().getStandardName()) + "Dao.xml",
							this.mybatisOracleDaoXmlDecorator.generateMybatisDaoXmlFileStr());
				}
	
				if (this.getService() != null) {
					writeToFile(srcfolderPath + "service/"+ StringUtil.capFirst(this.getDomain().getStandardName())
							+ "Service.java", this.getService().generateServiceString());
				}
	
				if (this.getServiceImpl() != null) {
					writeToFile(srcfolderPath + "serviceimpl/" +StringUtil.capFirst(this.getDomain().getStandardName())
							+ "ServiceImpl.java", this.getServiceImpl().generateServiceImplString());
				}
	
				if (this.controller != null) {
					writeToFile(srcfolderPath + "controller/"+StringUtil.capFirst(this.domain.getCapFirstDomainName())
							+ "Controller.java", this.controller.generateControllerString());
				}

				for (JsonPagingGridJspTemplate jsontp : this.jsonjsptemplates) {
					OracleEasyUIPageTemplate etp = (OracleEasyUIPageTemplate)jsontp;
					etp.setTitle(this.title);
					etp.setSubTitle(this.subTitle);
					etp.setFooter(this.footer);
					writeToFile(projectFolderPath + "src/main/resources/static/pages/"+this.domain.getPlural().toLowerCase() + ".html",
							etp.generateJspString());
				}
				
				for (ManyToMany mtm : this.manyToManies) {
					OracleManyToMany omtm = (OracleManyToMany)mtm;
					omtm.setTitle(this.title);
					omtm.setSubTitle(this.subTitle);
					omtm.setFooter(this.footer);
					writeToFile(projectFolderPath + "src/main/resources/static/pages/" + omtm.getEuTemplate().getStandardName().toLowerCase()  + ".html",
							mtm.getEuTemplate().generateContentString());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void generatePrismFromDomain() throws ValidateException, Exception {
		if (this.domain != null) {
			if (this.getPackageToken() != null) {
				this.domain.setPackageToken(packageToken);
			}
			
			this.domain.decorateCompareTo();

			this.dao = new Dao();
			this.dao.setDomain(this.domain);
			this.dao.setPackageToken(this.domain.getPackageToken());
			this.daoimpl = new DaoImpl();
			this.daoimpl.setPackageToken(this.domain.getPackageToken());
			this.daoimpl.setDomain(this.domain);
			this.daoimpl.setDao(this.dao);

			this.service = new Service();
			this.service.setDomain(this.domain);
			this.service.setPackageToken(this.domain.getPackageToken());
			this.serviceimpl = new ServiceImpl(this.domain);
			this.serviceimpl.setPackageToken(this.domain.getPackageToken());
			this.serviceimpl.getDao().addAnnotation("Autowired");
			Method daoSetter = NamedUtilMethodGenerator.generateSetter("dao",
					new Type(this.domain.getCapFirstDomainName() + "Dao"));
			this.serviceimpl.addMethod(daoSetter);
			this.serviceimpl.addClassImports("org.springframework.beans.factory.annotation.Autowired");
			this.serviceimpl.setDomain(this.domain);
			this.serviceimpl.setService(this.service);

			Verb listAll = new ListAll(this.domain);
			Verb update = new Update(this.domain);
			Verb delete = new Delete(this.domain);
			Verb add = new Add(this.domain);
			Verb softdelete = new SoftDelete(this.domain);
			Verb findbyid = new FindById(this.domain);
			Verb findbyname = new FindByName(this.domain);
			Verb searchbyname = new SearchByName(this.domain);
			Verb listactive = new ListActive(this.domain);
			Verb listAllByPage = new ListAllByPage(this.domain);
			Verb deleteAll = new DeleteAll(this.domain);
			Verb softDeleteAll = new SoftDeleteAll(this.domain);
			Verb toggle = new Toggle(this.domain);
			Verb toggleOne = new ToggleOne(this.domain);
			Verb searchByFieldsByPage = new SearchByFieldsByPage(this.domain);
			Verb activate = new Activate(this.domain);
			Verb activateAll = new ActivateAll(this.domain);
			Verb export = new Export(this.domain);
			Verb exportPDF = new ExportPDF(this.domain);
			Verb searchByFields = new SearchByFields(this.domain);
			Verb filterExcel = new FilterExcel(this.domain);
			Verb filterPDF = new FilterPDF(this.domain);
			Verb clone	= new Clone(this.domain);
			Verb cloneAll = new CloneAll(this.domain);

			CountAllPage countAllPage = new CountAllPage(this.domain);
			CountSearchByFieldsRecords countSearch = new CountSearchByFieldsRecords(this.domain);
			CountActiveRecords countActiveRecords = new CountActiveRecords(this.domain);

			this.addVerb(listAll);
			this.addVerb(update);
			this.addVerb(delete);
			this.addVerb(add);
			this.addVerb(softdelete);
			this.addVerb(findbyid);
			this.addVerb(findbyname);
			this.addVerb(searchbyname);
			this.addVerb(listactive);
			this.addVerb(listAllByPage);
			this.addVerb(deleteAll);
			this.addVerb(softDeleteAll);
			this.addVerb(toggle);
			this.addVerb(toggleOne);
			this.addVerb(searchByFieldsByPage);
			this.addVerb(activate);
			this.addVerb(activateAll);
			this.addVerb(export);
			this.addVerb(exportPDF);
			this.addVerb(searchByFields);
			this.addVerb(filterExcel);
			this.addVerb(filterPDF);
			this.addVerb(clone);
			this.addVerb(cloneAll);

			this.noControllerVerbs.add(countAllPage);
			this.noControllerVerbs.add(countSearch);
			this.noControllerVerbs.add(countActiveRecords);
			this.controller = new SpringMVCController(this.verbs, this.domain);
			this.controller.setPackageToken(this.packageToken);

			for (Verb v : this.verbs) {
				v.setDomain(domain);
				service.addMethod(v.generateServiceMethodDefinition());
				serviceimpl.addMethod(v.generateServiceImplMethod());
				dao.addMethod(v.generateDaoMethodDefinition());
				daoimpl.addMethod(v.generateDaoImplMethod());
				controller.addMethod(v.generateControllerMethod());
			}

			for (NoControllerVerb nVerb : this.noControllerVerbs) {
				nVerb.setDomain(domain);
				service.addMethod(nVerb.generateServiceMethodDefinition());
				serviceimpl.addMethod(nVerb.generateServiceImplMethod());
				dao.addMethod(nVerb.generateDaoMethodDefinition());
				daoimpl.addMethod(nVerb.generateDaoImplMethod());
			}

			for (DaoOnlyVerb oVerb : this.daoOnlyVerbs) {
				oVerb.setDomain(domain);
				dao.addMethod(oVerb.generateDaoMethodDefinition());
				daoimpl.addMethod(oVerb.generateDaoImplMethod());
			}

			this.mybatisOracleDaoXmlDecorator = new MybatisOracleDaoXmlDecorator();
			this.mybatisOracleDaoXmlDecorator.setDomain(this.getDomain());
			Set<Domain> resultMaps = new TreeSet<Domain>();
			resultMaps.add(this.domain);
			this.mybatisOracleDaoXmlDecorator.setResultMaps(resultMaps);
			Set<Method> daoimplMethods = new TreeSet<Method>();
			for (Verb vb : this.verbs) {
				if (vb!=null && vb.generateDaoImplMethod()!=null){
					daoimplMethods.add(vb.generateDaoImplMethod());
				}
			}
			for (DaoOnlyVerb dovb : this.daoOnlyVerbs) {
				if (dovb!=null && dovb.generateDaoImplMethod()!=null){
					daoimplMethods.add(dovb.generateDaoImplMethod());
				}
			}
			for (NoControllerVerb ncvb : this.noControllerVerbs) {
				if (ncvb!=null && ncvb.generateDaoImplMethod()!=null){
					daoimplMethods.add(ncvb.generateDaoImplMethod());
				}
			}
			this.mybatisOracleDaoXmlDecorator.setDaoXmlMethods(daoimplMethods);

			OracleEasyUIPageTemplate easyui = new OracleEasyUIPageTemplate();
			easyui.setDomain(this.domain);
			easyui.setStandardName(this.domain.getStandardName().toLowerCase());
			easyui.setTitle(this.title);
			easyui.setSubTitle(this.subTitle);
			easyui.setFooter(this.footer);
			easyui.setResolution(this.getResolution());
			this.addJsonJspTemplate(easyui);

			if (this.domain.getManyToManies() != null && this.domain.getManyToManies().size() > 0) {
				for (ManyToMany mtm : this.domain.getManyToManies()) {
					String slaveName = mtm.getManyToManySalveName();
					String masterName = this.domain.getStandardName();
					if (setContainsDomain(this.projectDomains, masterName)
							&& setContainsDomain(this.projectDomains, slaveName)) {
						
						Domain myslave = (Domain)lookupDoaminInSet(this.projectDomains, slaveName).deepClone();
						if (!StringUtil.isBlank(mtm.getSlaveAlias())){
							myslave.setAlias(mtm.getSlaveAlias());
							myslave.setAliasLabel(mtm.getSlaveAliasLabel());
						}
						OracleManyToMany mymtm = new OracleManyToMany(lookupDoaminInSet(this.projectDomains, masterName),
								myslave,mtm.getMasterValue(),mtm.getValues());	
						mymtm.setSlaveAlias(myslave.getAlias());
						EasyUIManyToManyTemplate eumpt = mymtm.getEuTemplate();
						eumpt.setResolution(this.getResolution());
						mymtm.setEuTemplate(eumpt);
						this.manyToManies.add(mymtm);
						System.out.println("JerryDebug:"+mymtm+":Master:"+masterName+":"+myslave.getAlias()+"");
					} else {
						ValidateInfo validateInfo = new ValidateInfo();
						validateInfo.addCompileError("棱柱" + this.getText() + "多对多设置有误。");
						ValidateException em = new ValidateException(validateInfo);
						throw em;
					}
				}
			}
			for (ManyToMany mtm : this.manyToManies) {
				OracleManyToMany omtm = (OracleManyToMany) mtm;
				omtm.setTitle(this.title);
				omtm.setSubTitle(this.subTitle);
				omtm.setFooter(this.footer);
				omtm.setCrossOrigin(this.crossOrigin);
				this.service.addMethod(omtm.getOracleAssign().generateServiceMethodDefinition());
				this.serviceimpl.addMethod(omtm.getOracleAssign().generateServiceImplMethod());
				this.dao.addMethod(omtm.getOracleAssign().generateDaoMethodDefinition());
				this.daoimpl.addMethod(omtm.getOracleAssign().generateDaoImplMethod());
				this.mybatisOracleDaoXmlDecorator.addDaoXmlMethod(omtm.getOracleAssign().generateDaoImplMethod());
				this.controller.addMethod(omtm.getOracleAssign().generateControllerMethod());

				this.service.addMethod(omtm.getOracleRevoke().generateServiceMethodDefinition());
				this.serviceimpl.addMethod(omtm.getOracleRevoke().generateServiceImplMethod());
				this.dao.addMethod(omtm.getOracleRevoke().generateDaoMethodDefinition());
				this.daoimpl.addMethod(omtm.getOracleRevoke().generateDaoImplMethod());
				this.mybatisOracleDaoXmlDecorator.addDaoXmlMethod(omtm.getOracleRevoke().generateDaoImplMethod());
				this.controller.addMethod(omtm.getOracleRevoke().generateControllerMethod());

				this.service.addMethod(omtm.getOracleListMyActive().generateServiceMethodDefinition());
				this.serviceimpl.addMethod(omtm.getOracleListMyActive().generateServiceImplMethod());
				this.dao.addMethod(omtm.getOracleListMyActive().generateDaoMethodDefinition());
				this.daoimpl.addMethod(omtm.getOracleListMyActive().generateDaoImplMethod());
				this.mybatisOracleDaoXmlDecorator.addResultMap(omtm.getSlave());
				this.mybatisOracleDaoXmlDecorator.addDaoXmlMethod(omtm.getOracleListMyActive().generateDaoImplMethod());
				this.controller.addMethod(omtm.getOracleListMyActive().generateControllerMethod());

				this.service.addMethod(omtm.getOracleListMyAvailableActive().generateServiceMethodDefinition());
				this.serviceimpl.addMethod(omtm.getOracleListMyAvailableActive().generateServiceImplMethod());
				this.dao.addMethod(omtm.getOracleListMyAvailableActive().generateDaoMethodDefinition());
				this.daoimpl.addMethod(omtm.getOracleListMyAvailableActive().generateDaoImplMethod());
				//this.mybatisOracleDaoXmlDecorator.addDaoXmlMethod(omtm.getOracleListMyAvailableActive().generateDaoImplMethod());
				this.controller.addMethod(omtm.getOracleListMyAvailableActive().generateControllerMethod());
				//omtm.getSlave().decorateCompareTo();
				
				Service slaveService = new Service();
				slaveService.setDomain(omtm.getSlave());
				slaveService.addAnnotation("Autowired");
				slaveService.setStandardName(omtm.getSlave().getCapFirstDomainName() + "Service");
				
				Method slaveServiceSetter = NamedUtilMethodGenerator.generateSetter(omtm.getSlave().getLowerFirstDomainName()+"Service",
						new Type(omtm.getSlave().getCapFirstDomainName() + "Service",mtm.getSlave().getPackageToken()+".service."+mtm.getSlave().getCapFirstDomainName() + "Service"));
				this.serviceimpl.addMethod(slaveServiceSetter);
				this.serviceimpl.addOtherService(slaveService);
			}
		}
	}
}
